package com.ziven.common.widget.window;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.ziven.common.widget.R;
import com.ziven.common.widget.value.TakeEffect;
import com.ziven.common.widget.value.Value;
import com.ziven.easygo.design.mvp.AbstractOneData;
import com.ziven.easygo.design.mvp.OneModel;
import com.ziven.easygo.design.mvp.OnePresenter;
import com.ziven.easygo.ui.AbstractEasyViewHolder;
import com.ziven.easygo.ui.AbstractOneDataFragment;
import com.ziven.easygo.ui.AbstractTypeAdapter;
import com.ziven.easygo.ui.AbstractTypeData;
import com.ziven.easygo.ui.OnItemClickListener;
import com.ziven.easygo.util.EasyUtils;
import com.ziven.easygo.util.ViewHelper;

import java.util.List;
import java.util.Map;

/**
 * @author Ziven
 */
public abstract class CommonFragment<T extends AbstractTypeData> extends AbstractOneDataFragment implements OnItemClickListener<T> {

    public static final int TYPE_SET = -101;
    public static final int TYPE_ADD = -102;
    public final CommonAdapter adapter = new CommonAdapter();

    @NonNull
    @Override
    protected Class<? extends OneModel> obtainOneModelClass() {
        return CommonModel.class;
    }

    @Nullable
    @Override
    protected OnePresenter obtainOnePresenter(@NonNull Class<? extends OneModel> cls) {
        return new OnePresenter(new CommonModel());
    }

    @Override
    protected Object obtainLayout() {
        return R.layout.fragment_recyclerview_container;
    }

    @Override
    protected void createdView(@NonNull View root) {
        adapter.setListener(this);
        getViewHelper(R.id.recycler_view)
                .setLayoutManager(obtainLayoutManager(root.getContext()))
                .setAdapter(adapter)
                .getViewNulls()
                .doNotNull(view -> obtainEffectValue().takeEffect(view));
        createdView2(root);
        if(requestAfterCreated()) {
            getOnePresenter().obtainOneData();
        }
    }

    protected void createdView2(@NonNull View root) {

    }

    @Override
    protected void destroyView() {

    }

    @Override
    public void layoutOneData(@NonNull AbstractOneData data) {
        List<T> list = data.getOneData();
        if(list == null || list.isEmpty()) {
            return;
        }
        if(TYPE_SET == data.getOneCode()) {
            layoutOneData2(false, list);
            adapter.getDataProvider().setList(list);
        } else {
            layoutOneData2(true, list);
            adapter.getDataProvider().addList(list);
        }
        EasyUtils.notifyDataSetChanged(adapter);
    }

    protected void layoutOneData2(boolean isAdd, @NonNull List<T> list) {

    }

    public class CommonModel extends OneModel {

        public CommonModel() {}

        @Override
        protected void obtainOneData(@Nullable Context c, @Nullable Map<Object, Object> params) {
            obtainItemData(this, c, params);
        }

        @Override
        public void obtainedOneData(@NonNull AbstractOneData data) {
            super.obtainedOneData(data);
        }
    }

    public class CommonAdapter extends AbstractTypeAdapter<T, CommonHolder> {

        @NonNull
        @Override
        public CommonHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            Object layout = obtainItemLayout(parent.getContext(), viewType);
            if(layout instanceof Integer) {
                return new CommonHolder(parent, (int) layout);
            }
            if(layout instanceof View) {
                return new CommonHolder((View) layout);
            }
            throw new RuntimeException("obtainItemLayout return object is not View or View Id.");
        }
    }

    public class CommonHolder extends AbstractEasyViewHolder<T> {

        public CommonHolder(@NonNull View itemView) {
            super(itemView);
        }

        public CommonHolder(@NonNull ViewGroup parent, int layoutId) {
            super(parent, layoutId);
        }

        @Override
        protected void bindLayout(T data, int position) {
            if(data != null) {
                bindItemLayout(this, data, position);
            }
        }

        @Override
        public <V extends View> V getView(@IdRes int id) {
            return super.getView(id);
        }

        @Override
        @NonNull
        public ViewHelper<View> getViewHelper(@IdRes int id) {
            return super.getViewHelper(id);
        }
    }

    protected boolean requestAfterCreated() {
        return true;
    }

    protected Value obtainEffectValue() {
        return TakeEffect.values();
    }

    @NonNull
    protected RecyclerView.LayoutManager obtainLayoutManager(Context context) {
        return new LinearLayoutManager(context);
    }

    /**
     * Obtain item data
     * @param model CommonModel
     * @param context Context
     * @param params Params
     */
    protected abstract void obtainItemData(@NonNull CommonModel model, @Nullable Context context, @Nullable Map<Object, Object> params);

    /**
     * Obtain item layout
     * @param context Context
     * @param viewType View type
     * @return View or View id
     */
    @NonNull
    protected abstract Object obtainItemLayout(@NonNull Context context, int viewType);

    /**
     * Bind item layout
     * @param holder CommonHolder
     * @param data Data
     * @param position Position
     */
    protected abstract void bindItemLayout(@NonNull CommonHolder holder, @NonNull T data, int position);
}
